<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      input[type='checkbox'] {
        width: 50px;
        height: 50px;
      }
    </style>
  </head>
  <body>
    <div>
      <button id="Undo">撤销</button>
      <button id="Redo">恢复</button>
    </div>
    <input type="checkbox" value="1" onchange="handlerChange(event)" />
    <input type="checkbox" value="2" onchange="handlerChange(event)" />
    <input type="checkbox" value="3" onchange="handlerChange(event)" />
    <input type="checkbox" value="4" onchange="handlerChange(event)" />
    <input type="checkbox" value="5" onchange="handlerChange(event)" />
    <input type="checkbox" value="6" onchange="handlerChange(event)" />
    <input type="checkbox" value="7" onchange="handlerChange(event)" />
    <input type="checkbox" value="8" onchange="handlerChange(event)" />
    <input type="checkbox" value="9" onchange="handlerChange(event)" />
    <input type="checkbox" value="10" onchange="handlerChange(event)" />
    <input type="checkbox" value="11" onchange="handlerChange(event)" />
    <input type="checkbox" value="12" onchange="handlerChange(event)" />
    <input type="checkbox" value="13" onchange="handlerChange(event)" />
    <input type="checkbox" value="14" onchange="handlerChange(event)" />
    <input type="checkbox" value="15" onchange="handlerChange(event)" />
    <input type="checkbox" value="16" onchange="handlerChange(event)" />
    <input type="checkbox" value="17" onchange="handlerChange(event)" />
    <input type="checkbox" value="18" onchange="handlerChange(event)" />
    <input type="checkbox" value="19" onchange="handlerChange(event)" />
    <input type="checkbox" value="20" onchange="handlerChange(event)" />
  </body>
  <script>
    const stack = [];
    let hand = -1; // 指针
    const Undo = document.getElementById('Undo');
    const Redo = document.getElementById('Redo');

    // 重置
    function reset() {
      const inputs = document.querySelectorAll('input');
      inputs.forEach((input) => {
        input.checked = false;
      });
    }

    function getElementByAttr(tag, attr, value) {
      var aElements = document.getElementsByTagName(tag);
      var aEle = [];
      for (var i = 0; i < aElements.length; i++) {
        if (aElements[i].getAttribute(attr) == value) {
          aEle.push(aElements[i]);
        }
      }
      return aEle;
    }

    function handlerChange(event) {
      const value = event.target.value;
      const checked = event.target.checked;
      stack.push({
        type: 'add',
        value,
        checked,
      });
      hand = stack.length - 1;
    }

    Undo.addEventListener('click', function (e) {
      console.log('Undo');

      if (hand === -1) return;
      hand--;
      reset();

      for (let index = 0; index <= hand; index++) {
        const element = stack[index];
        const dom = getElementByAttr('input', 'value', element.value)[0];
        dom.checked = element.checked;
      }
    });
    Redo.addEventListener('click', function (e) {
      console.log('Redo');
      if (hand === stack.length - 1) return;
      hand++;
      reset();

      for (let index = 0; index <= hand; index++) {
        const element = stack[index];
        const dom = getElementByAttr('input', 'value', element.value)[0];
        dom.checked = element.checked;
      }
    });
  </script>
</html>
